//=============================================================================
/**
 *
 *	@file		d_hosaka.c
 *	@brief		保坂用デバッグ 非常駐
 *	@author		hosaka genya
 *	@data		2008.08.01
 *
 */
//=============================================================================

#ifdef PM_DEBUG

#include "common.h"

#include "system/wipe.h"
#include "system/lib_pack.h"
#include "system/bmp_list.h"
#include "system/bmp_menu.h"
#include "system/fontproc.h"
#include "system/window.h"
#include "system/numfont.h"
#include "system/arc_util.h"
#include "system/snd_tool.h"
#include "system/snd_system.h"
#include "system/bmp_cursor.h"
#include "system/msgdata_util.h"

#include "savedata/phc_svdata.h"
#include "poketool/poke_tool.h"

#include "fld_bmp.h"
#include "fieldmap.h"
#include "fieldsys.h"
#include "fieldmap_work.h"

#include "field/eventflag.h"
#include "field/evwkdef.h"
#include "fielddata/script/saveflag.h"

#include "msgdata/msg_debug_hosaka.h"
#include "msgdata/msg.naix"

#include "system/touchpanel_draw.h"
#include "field_light.h"
#include "field_glb_state.h"
#include "talk_msg.h"

#include "savedata/zukanwork.h"

#include "application/museum.h"
#include "application/bug_select.h"
#include "application/phc_diary.h"

#include "application/pokethlon_frame.h"

#include "d_hosaka.h"
#include "d_hosaka_local.h"

#define APPLICATION_FADE_SYNC	(16)
#define TCB_PRI_DEBUG (1)	/// 常駐側のTCBが0なのでそれ以下にすること

#ifdef PM_DEBUG
// デバッグメニューからミュージアムを呼ぶときにダミーデータをセットする
//#define SET_PKTH_DUMMY_DATA
#endif


//=============================================================================
//	 						-- structures --
//=============================================================================

//-------------------------------------
///		デバッグメニュー制御ワーク
//=====================================
typedef struct {
	u8	work;
	GF_BGL_BMPWIN	*	p_bmpwin;
	BMPLIST_WORK	*	p_listwk;
	BMPLIST_DATA	*	p_listdata;

	u16				debug_list;
	u16				debug_cursor;
}DEBUG_MENU_CTRL_WORK;

//-------------------------------------
///		ウィンドウの文字と実行関数
//=====================================
typedef struct
{
	u32  str_id;
	u32  param;
}LIST_PARAM;

//-------------------------------------
///		デバッグウィンドウの情報
//=====================================
typedef struct {
	u16 debug_list;
	u16 debug_cursor;

	GF_BGL_BMPWIN		win;
	BMPLIST_WORK		*lw;		// BMPメニューワーク
	BMP_MENULIST_DATA 	*ld;

	BOOL b_no_exit;	///< メニュー終了しないフラグ
}DEBUG_WINDOW_DATA;

//=============================================================================
//						-- Global Valiable --
//=============================================================================
static FIELDSYS_WORK* sp_fldsys	= NULL;

//=============================================================================
//	 						-- prottypes --
//=============================================================================
// -- extern --
void DebugHosakaMenuInit(FIELDSYS_WORK* p_fldsys);
// -- list window --
static void	MoveLineCallBack(BMPLIST_WORK* lw,u32 param,u8 y);
static void MakeBmpList( int inNum, const LIST_PARAM *list, const BMPWIN_DAT * win_dat );
static void InitDebugWindow(DEBUG_WINDOW_DATA *wp);
static void DebugListFree(void* work);
static void FreeDebugWindow(void* work);
static void DebugWindowExit(TCB_PTR tcb,void* work);
static void DebugListControlTask(TCB_PTR tcb,void* work);
static void DebugNoExit( DEBUG_WINDOW_DATA* wp );
// -- call application --
static D_HOSAKA_APPLICATION_WORK* APPLICATION_AllocWork( int heap_id, u32 param_size );
// -- my scene --
// ++ PokeThlon Museun ++
static void PkthMuseumCourse_SetProc( void* work );
static void PkthMuseumPokemon_SetProc( void* work );
static void PkthMuseumEvent_SetProc( void* work );
static void PkthMuseumTrainer_SetProc( void* work );
static void CallPkthMuseumCourse( TCB_PTR p_tcb, void* p_wk );
static void CallPkthMuseumPoke( TCB_PTR p_tcb, void* p_wk );
static void CallPkthMuseumEvent( TCB_PTR p_tcb, void* p_wk );
static void CallPkthMuseumTrainer( TCB_PTR p_tcb, void* p_wk );
// ++ BugSelect ++
static void BugSelect_FreeWork( void* work );
static void BugSelect_SetProc( void* work );
static void CallBugSelect( TCB_PTR p_tcb, void* p_wk );
// ++ PhcDiary ++
static void PhcDiary_SetProc( void* work );
static void PhcDiary_FreeWork( void* work );
static void CallPhcDiary( TCB_PTR p_tcb, void* p_wk );
// ++ 連れ歩き表彰状 ++
static void PairSyoujyou_SetProc( void* work );
static void PairSyoujyou_FreeWork( void* work );
static void CallPairSyoujyou( TCB_PTR p_tcb, void* p_wk );
// ++ PokeThlon Museum Trophy ++
static void SetPkthNextTrophyPoke( TCB_PTR p_tcb, void* p_wk );
// ++ PokeThlon Museum Open Flag ++
static void SetPkthMuseumOpen02( TCB_PTR p_tcb, void* p_wk );
static void SetPkthMuseumOpen03( TCB_PTR p_tcb, void* p_wk );
static void SetPkthMuseumOpen04( TCB_PTR p_tcb, void* p_wk );
// ++ PokeThlon Data Set ++
static void SetPkthResetEventAloneData( TCB_PTR p_tcb, void* p_wk );
static void SetPkthResetEventCommData( TCB_PTR p_tcb, void* p_wk );
static void CallPkthDataSet( TCB_PTR p_tcb, void* p_wk );
// ++ Pokethlon Effort ++
static void CallEffortList( TCB_PTR p_tcb, void* p_wk );
// ++ Pokethlon Rank ++
static void CallSetPkthRank( TCB_PTR p_tcb, void* p_wk );

//=============================================================================
//	 						-- data table --
//=============================================================================

//=============================================================================
//
///	ウィンドウのデータ
//
//=============================================================================
//-------------------------------------
///		ウィンドウの範囲情報など
//=====================================
//	メインウィンドウ
static const BMPWIN_DAT	MainDebugListWindowData = {
	FLD_MBGFRM_FONT,
	0,0,
	16,24,
	FLD_SYSFONT_PAL,
	8
};

//=============================================================================
//-------------------------------------
///		ウィンドウの項目
//=====================================
//	メインウィンドウ
static const LIST_PARAM MainDebugList[] = {
	{MSG_PAIR_SYOUJYOU,			(u32)CallPairSyoujyou},
	{MSG_PHC_DIARY,				(u32)CallPhcDiary},
	{MSG_BUG_SELECT,			(u32)CallBugSelect},
	{MSG_RABEL_PKTH_APP,		BMPLIST_RABEL},
	{MSG_PKTH_MUSEUM_COURSE,	(u32)CallPkthMuseumCourse},
	{MSG_PKTH_MUSEUM_POKE,		(u32)CallPkthMuseumPoke},
	{MSG_PKTH_MUSEUM_EVENT,		(u32)CallPkthMuseumEvent},
	{MSG_PKTH_MUSEUM_TRAINER,	(u32)CallPkthMuseumTrainer},
	{MSG_RABEL_PKTH_SET,		BMPLIST_RABEL},
	{MSG_PKTH_RANK_SET,			(u32)CallSetPkthRank},
	{MSG_PKTH_SET_EVT_DATA,		(u32)CallPkthDataSet},
	{MSG_PKTH_NEXT_TROPHY_POKE,	(u32)SetPkthNextTrophyPoke},
	{MSG_PKTH_MUSEUM_OPEN_02,	(u32)SetPkthMuseumOpen02},
	{MSG_PKTH_MUSEUM_OPEN_03,	(u32)SetPkthMuseumOpen03},
	{MSG_PKTH_MUSEUM_OPEN_04,	(u32)SetPkthMuseumOpen04},
	{MSG_PKTH_RESET_EVT_ALONE,	(u32)SetPkthResetEventAloneData},
	{MSG_PKTH_RESET_EVT_COMM,	(u32)SetPkthResetEventCommData},
	{MSG_RABEL_PKTH_DEBUG,		BMPLIST_RABEL},
	{MSG_PKTH_EFFORT_SELECT,	(u32)CallEffortList},
	{MSG_CLOSE,(u32)DebugWindowExit},
};

//=============================================================================
/**
 *								外部公開関数
 */
//=============================================================================
void DebugHosakaMenuInit(FIELDSYS_WORK* p_fldsys)
{
	sp_fldsys	= p_fldsys;
	MakeBmpList( NELEMS(MainDebugList), MainDebugList, &MainDebugListWindowData);
}

static void APPLICATION_FreeWork( D_HOSAKA_APPLICATION_WORK* p_wk );

// アプリ遷移 メイン
void DebugHosakaMenuMain( TCB_PTR p_tcb, void * p_work )
{
	enum {
		SEQ_FADEOUT_START,
		SEQ_FADEOUT_WAIT,
		SEQ_PROC_START,
		SEQ_PROC_WAIT,
		SEQ_FLDPRCRET_START,
		SEQ_FLDPRCRET_WAIT,
		SEQ_FADEIN_START,
		SEQ_FADEIN_WAIT,
		SEQ_END,
	};

	D_HOSAKA_APPLICATION_WORK *p_wk = p_work;

	switch( p_wk->seq ){
	case SEQ_FADEOUT_START:

		p_wk->bgm_no	= Snd_NowBgmNoGet();
		WIPE_SYS_Start(WIPE_PATTERN_WMS,WIPE_TYPE_FADEOUT,WIPE_TYPE_FADEOUT,
				WIPE_FADE_BLACK, APPLICATION_FADE_SYNC,1,HEAPID_FIELD
				);
		p_wk->seq = SEQ_FADEOUT_WAIT;
		break;

	case SEQ_FADEOUT_WAIT:
		if(WIPE_SYS_EndCheck()){
			p_wk->seq = SEQ_PROC_START;
		}
		break;

	case SEQ_PROC_START:
		p_wk->SetProcFunction( p_wk->p_param );
		FieldSystemProc_SeqHoldEnd();
		p_wk->seq = SEQ_PROC_WAIT;
		break;

	case SEQ_PROC_WAIT:
		if( !FieldEvent_Cmd_WaitSubProcEnd( p_wk->fsys ) ){
			p_wk->seq	= SEQ_FLDPRCRET_START;
		}
		break;

	case SEQ_FLDPRCRET_START:
		//フィールドマッププロセス復帰
		FieldEvent_Cmd_SetMapProc(p_wk->fsys);
		p_wk->seq	= SEQ_FLDPRCRET_WAIT;
		break;

	case SEQ_FLDPRCRET_WAIT:
		//フィールドプロセス開始終了待ち
		if(FieldEvent_Cmd_WaitMapProcStart(p_wk->fsys)){
			p_wk->seq	= SEQ_FADEIN_START;
		}
		break;

	case SEQ_FADEIN_START:
		//ブラックインリクエスト
		WIPE_SYS_Start(WIPE_PATTERN_WMS,WIPE_TYPE_FADEIN,WIPE_TYPE_FADEIN,
				WIPE_FADE_BLACK, APPLICATION_FADE_SYNC,1,HEAPID_FIELD
				);
		Snd_BgmPlay(p_wk->bgm_no);
		p_wk->seq	= SEQ_FADEIN_WAIT;
		break;

	case SEQ_FADEIN_WAIT:
		if(WIPE_SYS_EndCheck()){
			p_wk->seq	= SEQ_END;
		}
		break;

	case SEQ_END:
		HOSAKA_PRINT("フィールドに復帰\n");
		//	TCBとワークを削除
		APPLICATION_FreeWork( p_wk );
		DebugHosaka_FreeTcbAndUnloadOverlay( p_tcb );
		break;

	default : GF_ASSERT(0);
	}
}

//=============================================================================
/**
 *								static関数
 */
//=============================================================================

//----------------------------------------------------------------------------
/**
 *	@brief	アプリケーション用ワーク削除
 *
 *	@param	D_HOSAKA_APPLICATION_WORK* p_wk	削除するワーク
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void APPLICATION_FreeWork( D_HOSAKA_APPLICATION_WORK* p_wk )
{
	GF_ASSERT( p_wk );

	if( p_wk->DebugFreeFunc != NULL ) {
		p_wk->DebugFreeFunc( p_wk->p_param );
	}

	if( p_wk->p_param != NULL ) {
		sys_FreeMemoryEz( p_wk->p_param );
	}

	sys_FreeMemoryEz( p_wk );
}

//1行動くごとのコールバック
static void	MoveLineCallBack(BMPLIST_WORK* lw,u32 param,u8 y)
{
	if(param == BMPLIST_RABEL){
		BmpListTmpColorChange(lw,FBMP_COL_RED_SDW,FBMP_COL_BLACK,FBMP_COL_RED);
	}else{
		BmpListTmpColorChange(lw,FBMP_COL_WHITE,FBMP_COL_BLACK,FBMP_COL_BLK_SDW);
	}
}

//リスト作成
static void MakeBmpList( int inNum, const LIST_PARAM *list, const BMPWIN_DAT * win_dat )
{
	TCB_PTR pTcb;
	DEBUG_WINDOW_DATA *wp;

	BMPLIST_HEADER bmplist_h = {
		//MainDebugList,	//表示文字データポインタ
		NULL,				//表示文字データポインタ
		NULL,				//カーソル移動ごとのコールバック関数
		MoveLineCallBack,	//１行ごとのコールバック関数
		NULL,		//GF_BGL_BMPWIN *
		0,//リスト項目数
		0,//表示最大項目数
		2,					//ラベル表示Ｘ座標
		12,					//項目表示Ｘ座標
		1,					//カーソル表示Ｘ座標
		8,					//表示Ｙ座標
		FBMP_COL_WHITE,		//文字色
		FBMP_COL_BLACK,		//背景色
		FBMP_COL_BLK_SDW,	//文字影色
		0,					//文字間隔Ｘ
		1,					//文字間隔Ｙ
		BMPLIST_LRKEY_SKIP,	//ページスキップタイプ
		FONT_SYSTEM,			//文字指定
		0,					//ＢＧカーソル(allow)表示フラグ(0:ON,1:OFF)
		NULL,				//*work
	};

	wp = sys_AllocMemory(HEAPID_FIELD,sizeof(DEBUG_WINDOW_DATA));

	if(wp == NULL){
		//ワークエリアが取得できなければ何もしない
		HOSAKA_PRINT("map_num debug menu crate failed\n");
		return;
	}

	memset(wp,0,sizeof(DEBUG_WINDOW_DATA));

	//デバッグメニュー用変数初期化
	InitDebugWindow(wp);

	//メイン処理タスク追加
	pTcb = TCB_Add(DebugListControlTask, wp, TCB_PRI_DEBUG);

	wp->ld = BMP_MENULIST_Create( inNum, HEAPID_FIELD );
	{
		MSGDATA_MANAGER* msgman;
		int i;

		msgman = MSGMAN_Create(MSGMAN_TYPE_NORMAL, ARC_MSG, NARC_msg_debug_hosaka_dat, HEAPID_FIELD);
		for(i=0; i<inNum; i++)
		{
			BMP_MENULIST_AddArchiveString( wp->ld, msgman,
					list[i].str_id, list[i].param );
		}
		MSGMAN_Delete(msgman);
	}

	//BITMAPメニュー追加
	GF_BGL_BmpWinAddEx(sp_fldsys->bgl,&wp->win,win_dat);
	//BMPリスト設定
	bmplist_h.count = inNum;
	if (9 < inNum){
		bmplist_h.line = 9;
	}else{
		bmplist_h.line = inNum;
	}
	HOSAKA_PRINT("disp=%d\n",inNum);
	bmplist_h.list = wp->ld;
	bmplist_h.win = &wp->win;
	wp->lw = BmpListSet(&bmplist_h,0,0,HEAPID_FIELD);

	//イベントフック
	FieldSystemProc_SeqHold();
	return;

}

//===============================================================================
//	ウィンドウ共通
//===============================================================================
//初期化
static void InitDebugWindow(DEBUG_WINDOW_DATA *wp)
{
	wp->debug_list = 0;
	wp->debug_cursor = 0;
}
//リストの開放処理
static void DebugListFree(void* work)
{
	DEBUG_WINDOW_DATA	*wp;

	wp = (DEBUG_WINDOW_DATA*)work;

	//BMPウィンドウOFF
	GF_BGL_BmpWinOff(&wp->win);

	//BMPリスト破棄
	BmpListExit( wp->lw,&wp->debug_list,&wp->debug_cursor );
	//BMPWindow消去
	GF_BGL_BmpWinDel( &wp->win );
	return;
}
//デバッグウィンドウを解放
static void FreeDebugWindow(void* work)
{
	//リストの開放処理
	DebugListFree(work);
	//ワークメモリ開放
	sys_FreeMemoryEz(work);
}

//デバッグウィンドウ終了
static void DebugWindowExit(TCB_PTR tcb,void* work)
{
	//ウィンドウ解放
	FreeDebugWindow(work);
	//OBJ等の動作停止解除
	FieldSystemProc_SeqHoldEnd();//OBJ等の動作停止解除
	//メインタスク消去TCB開始
	DebugHosaka_FreeTcbAndUnloadOverlay( tcb );
}

//リストコントロール
static void DebugListControlTask(TCB_PTR tcb,void* work)
{
	s32	ret_code;
	TCB_FUNC	func;
	DEBUG_WINDOW_DATA	*wp;

	wp = (DEBUG_WINDOW_DATA*)work;

	ret_code = BmpListMain(wp->lw);

	// スクリーンが消されてしまうので苦肉の策
	GF_BGL_BmpWinOnVReq( &wp->win );

	//キー操作判定
	if(sys.trg & PAD_BUTTON_A){
		if(ret_code){
			func = (TCB_FUNC)ret_code;
			func(tcb,work);
			if( wp->b_no_exit )
			{
				wp->b_no_exit = 0;
			}
			else
			{
				// ウィンドウ描画後に消去してしまう…
				BMP_MENULIST_Delete( wp->ld );
				FreeDebugWindow(work);
			}
		}
		return;
	}
	//メニューキャンセル
	if(sys.trg & PAD_BUTTON_B){
		BMP_MENULIST_Delete( wp->ld );
		DebugWindowExit(tcb,work);
		return;
	}
}

// デバッグメニュー抜けないフラグON
static void DebugNoExit( DEBUG_WINDOW_DATA* wp )
{
	wp->b_no_exit = 1;
}

//=============================================================================
/**
 *		アプリケーション変移処理
 */
//=============================================================================
//----------------------------------------------------------------------------
/**
 *	@brief	アプリケーション用ワーク作成
 *
 *	@param	heap_id			ヒープID
 *	@param	param_size		サブワークエリア（0で作成しない）
 *
 *	@return	作成したワーク
 */
//-----------------------------------------------------------------------------
static D_HOSAKA_APPLICATION_WORK* APPLICATION_AllocWork( int heap_id, u32 param_size )
{
	D_HOSAKA_APPLICATION_WORK* p_wk = sys_AllocMemory( heap_id,sizeof(D_HOSAKA_APPLICATION_WORK) );
	MI_CpuClear8( p_wk, sizeof(D_HOSAKA_APPLICATION_WORK) );

	p_wk->DebugFreeFunc = NULL;
	p_wk->hold_work = NULL;
	p_wk->seq = 0;
	p_wk->fsys = sp_fldsys;

	if( param_size ) {
		p_wk->p_param	= sys_AllocMemory( heap_id,param_size );
		MI_CpuClear8( p_wk->p_param, param_size );
	}

	return p_wk;
}

static void set_monsdata( MONS_DATA* monsData )
{
	u8 monsno =  ( gf_mtRand() % (MONSNO_END-1 ) ) + 1;
	u32 rnd = gf_mtRand() % 9999;

	monsData->MonsNo = monsno;
	monsData->Rnd = rnd;
	monsData->Sex = PokeSexGetMonsNo( monsno, rnd );
}

static BOOL get_museum04_open_flag( SAVEDATA* p_sv )
{
	return (
		EventWork_CheckEventFlag( SaveData_GetEventWork(p_sv),	FE_PKTH_MUSEUM02_OPEN ) &&
		EventWork_CheckEventFlag( SaveData_GetEventWork(p_sv),	FE_PKTH_MUSEUM03_OPEN ) &&
		EventWork_CheckEventFlag( SaveData_GetEventWork(p_sv),	FE_PKTH_MUSEUM04_OPEN )
	);

}

//-- イベントデータをセット
static void set_event_data( PKTH_EVT_DATA* p_evt_dat )
{
	int j;
	p_evt_dat->EntryNum = gf_mtRand() % 10000000;
	for( j=0; j<BEST_FIVE; j++ )
	{
		p_evt_dat->RcMs[j].FrmMnsNo[0] = ( gf_mtRand() % (MONSNO_END-1 ) ) + 1;
		p_evt_dat->RcMs[j].FrmMnsNo[1] = ( gf_mtRand() % (MONSNO_END-1 ) ) + 1;
		p_evt_dat->RcMs[j].FrmMnsNo[2] = ( gf_mtRand() % (MONSNO_END-1 ) ) + 1;
		p_evt_dat->RcMs[j].Record = 10 * (BEST_FIVE - j) + ( gf_mtRand() % 10 );
	}
}

static void set_dummy_Data( void )
{
	int i, j;
	SAVEDATA* sv;
	PKTH_COURSE crs_dat[ 5 ];

#ifndef SET_PKTH_DUMMY_DATA
	return;
#endif

	sv = GameSystem_GetSaveData( sp_fldsys );

	//===============================================
	// Course Data
	//===============================================
	// 最後のメダルは未取得にしておくので4
	for( i=0; i<4; i++ )
	{
		int total = 0;

		for( j=0; j<3; j++ )
		{
			crs_dat[i].EvtScore[j] = gf_mtRand()%255;
			total += crs_dat[i].EvtScore[j];
		}

		crs_dat[i].MaxScore = total + gf_mtRand()%234;

		for( j=0; j<3; j++ )
		{
			set_monsdata( &crs_dat[i].MonsData[j] );
		}

		PkthlnSv_SetCrsDataAlone( PkthlnSv_GetSaveData( sv ), i, &crs_dat[i] );
	}

	{
		for( j=0; j<3; j++ )
		{
			set_monsdata( &crs_dat[i].MonsData[j] );
		}
		PkthlnSv_SetCrsDataAlone( PkthlnSv_GetSaveData( sv ), 4, &crs_dat[i] );
	}

	//===============================================
	// Event Data
	//===============================================
#if 1
	HOSAKA_PRINT( "set event data -->\n" );
	for( i=0; i<PKTHLN_EVT_MAX; i++ )
	{
		PKTH_EVT_DATA evt_dat = {0};
		PKTH_COMM_EVT_DATA evt_comm_dat = {0};

		//-- ひとり データ

		set_event_data( &evt_dat );

		if( i==0 )
		{
			evt_dat.RcMs[0].Record = 10;
			evt_dat.RcMs[1].Record = 40*30;
			evt_dat.RcMs[2].Record = 40*30+1;
			evt_dat.RcMs[3].Record = 60*30+2;
			evt_dat.RcMs[3].Record = 0xffff;
			MI_CpuClear8( evt_dat.RcMs[3].FrmMnsNo, sizeof(u16)*3 );
		}

		// 1 を弄る
		if( i==1 )
		{
			// 4位、5位を空にしてみる
			evt_dat.RcMs[3].Record = 0xffff;
			evt_dat.RcMs[4].Record = 0xffff;
		}
		else if( i==6 )
		{
			for( j=0; j<BEST_FIVE; j++ )
			{
				evt_dat.RcMs[j].Record *= 1024;
			}
		}

		PkthlnSv_SetEvtDataAlone( PkthlnSv_GetSaveData( sv ), i, &evt_dat );

		//-- つうしん データ
		for( j=0; j<BEST_FIVE; j++ )
		{
			static const STRCODE name[] = { A_, I_, U_, EOM_, };
			MI_CpuCopy8( name, evt_comm_dat.TrData[j].TrName, sizeof(name) );
		}
		set_event_data( &evt_comm_dat.EvtData );

		if( i != 3 )
		{
			PkthlnSv_SetEvtDataComm( PkthlnSv_GetSaveData( sv ), i, &evt_comm_dat );
		}
	}
	HOSAKA_PRINT( "<-- set event data end \n" );
#endif

	//===============================================
	// Medal Data
	//===============================================
	PkthlnSv_SetMedalData( PkthlnSv_GetSaveData( sv ), 0, 1 );
}

//-----------------------------------------------------------
// Course
//-----------------------------------------------------------
static void PkthMuseumCourse_SetProc( void* work )
{
	PKTH_MUSEUM_COURSE_PARAM* p_crsp = work;
	PKTHLN_SV_DATA_PTR pk_sv;
	SAVEDATA* p_sv;

	//オーバーレイID定義
	FS_EXTERN_OVERLAY(museum);

	//オーバーレイプロセス定義データ
	static const PROC_DATA CourseProcData = {
		MuseumCourseProc_Init,
		MuseumCourseProc_Main,
		MuseumCourseProc_End,
		FS_OVERLAY_ID(museum),
	};

	GF_ASSERT(p_crsp);

	set_dummy_Data();

	p_sv = GameSystem_GetSaveData( sp_fldsys );
	pk_sv = PkthlnSv_GetSaveData( p_sv );
	p_crsp->p_crs_dat = PkthlnSv_GetCrsDataAloneCnst( pk_sv );
	p_crsp->b_museum_open = get_museum04_open_flag( p_sv );

	GameSystem_StartSubProc( sp_fldsys, &CourseProcData, p_crsp );
}

static void CallPkthMuseumCourse( TCB_PTR p_tcb, void* p_wk )
{
	D_HOSAKA_APPLICATION_WORK* p_app_wk;

	//タスク消去
	TCB_Delete(p_tcb);

	p_app_wk	= APPLICATION_AllocWork( HEAPID_BASE_DEBUG, sizeof(PKTH_MUSEUM_COURSE_PARAM) );
	p_app_wk->SetProcFunction	= PkthMuseumCourse_SetProc;
	TCB_Add(DebugHosaka_CallApplication, p_app_wk, TCB_PRI_DEBUG);
}

//-----------------------------------------------------------
// Poke
//-----------------------------------------------------------
static void PkthMuseumPokemon_SetProc( void* work )
{
	PKTH_MUSEUM_PK_PARAM*	p_prm = work;
	SAVEDATA*				p_sv;
	PKTHLN_SV_DATA_PTR		pk_sv;
	const ZUKAN_WORK*		p_zkn;

	//オーバーレイID定義
	FS_EXTERN_OVERLAY(museum);

	//オーバーレイプロセス定義データ
	static const PROC_DATA PokemonProcData = {
		MuseumPokemonProc_Init,
		MuseumPokemonProc_Main,
		MuseumPokemonProc_End,
		FS_OVERLAY_ID(museum),
	};

	GF_ASSERT(p_prm);

	set_dummy_Data();

	p_sv	= GameSystem_GetSaveData( sp_fldsys );
	p_zkn	= SaveData_GetZukanWork( p_sv );
	pk_sv	= PkthlnSv_GetSaveData( p_sv );

	p_prm->p_zkn = p_zkn;
	p_prm->p_medal_dat = PkthlnSv_GetMedalDataCnst( pk_sv );
	p_prm->b_zukan_zenkoku = ZukanWork_GetZenkokuZukanFlag( p_zkn );
	p_prm->b_museum_open = get_museum04_open_flag( p_sv );

	GameSystem_StartSubProc( sp_fldsys, &PokemonProcData, p_prm );

}

static void CallPkthMuseumPoke( TCB_PTR p_tcb, void* p_wk )
{
	D_HOSAKA_APPLICATION_WORK* p_app_wk;

	//タスク消去
	TCB_Delete(p_tcb);

	p_app_wk					= APPLICATION_AllocWork( HEAPID_BASE_DEBUG, sizeof(PKTH_MUSEUM_PK_PARAM) );
	p_app_wk->SetProcFunction	= PkthMuseumPokemon_SetProc;

	TCB_Add(DebugHosaka_CallApplication, p_app_wk, TCB_PRI_DEBUG);
}

//-----------------------------------------------------------
// Event
//-----------------------------------------------------------
static void PkthMuseumEvent_SetProc( void* work )
{
	PKTH_MUSEUM_EV_PARAM*	p_prm = work;
	SAVEDATA*				p_sv;
	PKTHLN_SV_DATA_PTR		pk_sv;

	//オーバーレイID定義
	FS_EXTERN_OVERLAY(museum);

	//オーバーレイプロセス定義データ
	static const PROC_DATA EventProcData = {
		MuseumEventProc_Init,
		MuseumEventProc_Main,
		MuseumEventProc_End,
		FS_OVERLAY_ID(museum),
	};

	GF_ASSERT(p_prm);

	set_dummy_Data();

	p_sv = GameSystem_GetSaveData( sp_fldsys );
	pk_sv = PkthlnSv_GetSaveData( p_sv );

	p_prm->p_ev_alone	= PkthlnSv_GetEvtDataAloneCnst( pk_sv );
	p_prm->p_ev_comm	= PkthlnSv_GetEvtDataCommCnst( pk_sv );
	p_prm->p_st			= SaveData_GetMyStatus( p_sv );
	p_prm->b_museum_open = get_museum04_open_flag( p_sv );
	p_prm->p_best_score_dat = PkthlnSv_GetBestRecScore( pk_sv );

	GameSystem_StartSubProc( sp_fldsys, &EventProcData, p_prm );
}

static void CallPkthMuseumEvent( TCB_PTR p_tcb, void* p_wk )
{
	D_HOSAKA_APPLICATION_WORK* p_app_wk;

	//タスク消去
	TCB_Delete(p_tcb);

	p_app_wk	= APPLICATION_AllocWork( HEAPID_BASE_DEBUG, sizeof(PKTH_MUSEUM_EV_PARAM) );
	p_app_wk->SetProcFunction	= PkthMuseumEvent_SetProc;
	TCB_Add(DebugHosaka_CallApplication, p_app_wk, TCB_PRI_DEBUG);
}

//-----------------------------------------------------------
// Trainer
//-----------------------------------------------------------
static void PkthMuseumTrainer_SetProc( void* work )
{
	PKTH_MUSEUM_TR_PARAM*	p_trp = work;
	const MYSTATUS*			p_st;
	SAVEDATA*				p_sv;
	PKTHLN_SV_DATA_PTR		pk_sv;

	//オーバーレイID定義
	FS_EXTERN_OVERLAY(museum);

	//オーバーレイプロセス定義データ
	static const PROC_DATA TrainerProcData = {
		MuseumTrainerProc_Init,
		MuseumTrainerProc_Main,
		MuseumTrainerProc_End,
		FS_OVERLAY_ID(museum),
	};

	GF_ASSERT(p_trp);

	set_dummy_Data();

	p_sv = GameSystem_GetSaveData( sp_fldsys );
	p_st = SaveData_GetMyStatus( p_sv );
	pk_sv = PkthlnSv_GetSaveData( p_sv );

	p_trp->p_sv = pk_sv;
	p_trp->p_st = p_st;

	GameSystem_StartSubProc( sp_fldsys, &TrainerProcData, p_trp );

}

static void CallPkthMuseumTrainer( TCB_PTR p_tcb, void* p_wk )
{
	D_HOSAKA_APPLICATION_WORK* p_app_wk;

	//タスク消去
	TCB_Delete(p_tcb);

	p_app_wk	= APPLICATION_AllocWork( HEAPID_BASE_DEBUG, sizeof(PKTH_MUSEUM_TR_PARAM) );
	p_app_wk->SetProcFunction	= PkthMuseumTrainer_SetProc;
	TCB_Add(DebugHosaka_CallApplication, p_app_wk, TCB_PRI_DEBUG);
}

//-----------------------------------------------------------
// BugSelect
//-----------------------------------------------------------
static void BugSelect_SetProc( void* work )
{
	BUG_SELECT_PROC_PARAM*	p_prm = work;

	//オーバーレイID定義
	FS_EXTERN_OVERLAY(bug_select);

	//オーバーレイプロセス定義データ
	static const PROC_DATA BugSelectProcData = {
		BugSelectProc_Init,
		BugSelectProc_Main,
		BugSelectProc_End,
		FS_OVERLAY_ID(bug_select),
	};

	GF_ASSERT(p_prm);

	GameSystem_StartSubProc( sp_fldsys, &BugSelectProcData, p_prm );
}

static void BugSelect_FreeWork( void* work )
{
	int i;
	BUG_SELECT_PROC_PARAM*	p_prm = work;

	GF_ASSERT(p_prm);

	for( i=0; i<BUGSLT_POKE_MAX; i++ )
	{
		sys_FreeMemoryEz(p_prm->pPoke[i]);
	}
}

static void CallBugSelect( TCB_PTR p_tcb, void* p_wk )
{
	D_HOSAKA_APPLICATION_WORK* p_app_wk;

	//タスク消去
	TCB_Delete(p_tcb);

	p_app_wk	= APPLICATION_AllocWork( HEAPID_BASE_DEBUG, sizeof(BUG_SELECT_PROC_PARAM) );
	p_app_wk->SetProcFunction	= BugSelect_SetProc;
	p_app_wk->DebugFreeFunc	= BugSelect_FreeWork;

	{
		int i;
		BUG_SELECT_PROC_PARAM* p_prm = p_app_wk->p_param;

		GF_ASSERT(p_prm);

#ifdef PM_DEBUG
		// デバッグボタンを押していたらモード変更
		if( sys.cont & PAD_BUTTON_DEBUG )
		{
			p_prm->bFirstGet = 1;
		}
#endif

		// POKEMON_PARAM dummy create
		for( i=0; i<BUGSLT_POKE_MAX; i++ )
		{
			POKEMON_PARAM* p_poke;
			int poke_no = 1 + gf_mtRand() % (MONSNO_END-1);
			int level = 1 + gf_mtRand() % 100;

			p_prm->pPoke[i] = PokemonParam_AllocWork( HEAPID_BASE_DEBUG );
			PokeParaSet( p_prm->pPoke[i], poke_no, level, POW_RND, RND_NO_SET, 0, ID_NO_SET, 0 );
		}

		p_prm->cfg = SaveData_GetConfig( sp_fldsys->savedata );
	}

	TCB_Add(DebugHosaka_CallApplication, p_app_wk, TCB_PRI_DEBUG );
}

//-----------------------------------------------------------
// PHC Diary
//-----------------------------------------------------------
static void PhcDiary_SetProc( void* work )
{
	int i;
	PHC_DIARY_PARAM*	p_prm = work;

	//オーバーレイID定義
	FS_EXTERN_OVERLAY(phc);

	//オーバーレイプロセス定義データ
	static const PROC_DATA PhcDiaryProcData = {
		PhcDiaryProc_Init,
		PhcDiaryProc_Main,
		PhcDiaryProc_End,
		FS_OVERLAY_ID(phc),
	};

	GF_ASSERT(p_prm);

	GameSystem_StartSubProc( sp_fldsys, &PhcDiaryProcData, p_prm );
}

static void PhcDiary_FreeWork( void* work )
{
	int i;
	PHC_DIARY_PARAM* p_prm = work;

	GF_ASSERT(p_prm);

	sys_FreeMemoryEz( p_prm->pDiaryData );
}

static void CallPhcDiary( TCB_PTR p_tcb, void* p_wk )
{
	int i;
	D_HOSAKA_APPLICATION_WORK* p_app_wk;

	//タスク消去
	TCB_Delete(p_tcb);

	p_app_wk	= APPLICATION_AllocWork( HEAPID_BASE_DEBUG, sizeof(PHC_DIARY_PARAM) );
	p_app_wk->SetProcFunction	= PhcDiary_SetProc;
	p_app_wk->DebugFreeFunc = PhcDiary_FreeWork;

	{
		PHC_DIARY_PARAM* p_prm = p_app_wk->p_param;
		PHCDiary* pPHCD;

		// ダミーデータ宣言
		static const STRCODE YourName[] = { GA_, I_, ZI_, N_, EOM_, };
		static const STRCODE YourNick[] = { HO_, GE_, EOM_, };
		static const STRCODE MyNick[] = { TA_, MA_, NE_, GI_, EOM_, };
		static const STRCODE courseName[] = { ka_, ku_, si_, KO_, bou_, SU_, EOM_ };
		u8 courseId = gf_mtRand() % 8;
		int minute = 0;

		pPHCD = sys_AllocMemoryLo( HEAPID_BASE_APP, sizeof(PHCDiary)*PHC_DIA_DATA_MAX );
		MI_CpuClear8( pPHCD, sizeof(PHCDiary)*PHC_DIA_DATA_MAX );

		// セーブデータを受け渡し
		p_prm->pSaveData = GameSystem_GetSaveData( sp_fldsys );

		{
			// 預けた日
			GF_DATE date = GFDate_Set( 1, 1+gf_mtRand() % 12, 1+gf_mtRand() % 28, 0 );
			PhcSvData_SetPhcDepositDate( SaveData_GetPhcSaveData( p_prm->pSaveData ), date );
		}


#define PAGE_NUM (24)
		for( i=0; i<PAGE_NUM; i++ )
		{
			pPHCD[i].actionId = 1 + gf_mtRand() % 24;

			// テキトーに時間経過
			minute += 60 * 60; // gf_mtRand() % 255;

			pPHCD[i].rtcSecond = minute;
			pPHCD[i].pokeNumber = 1 + gf_mtRand() % MONSNO_END;
			pPHCD[i].mySex = PokeSexGetMonsNo( pPHCD[i].pokeNumber, gf_mtRand() );
			pPHCD[i].enemyNumber = 1 + gf_mtRand() % MONSNO_END;
			pPHCD[i].yourSex = PokeSexGetMonsNo( pPHCD[i].pokeNumber, gf_mtRand() );
			pPHCD[i].myStepHour = gf_mtRand() % 1000;
			pPHCD[i].yourStepHour = gf_mtRand() % 1000;
			pPHCD[i].myStepDay = gf_mtRand();
			pPHCD[i].yourStepDay = gf_mtRand();
			pPHCD[i].itemNumber = gf_mtRand() % 500;
			pPHCD[i].courseId = courseId;
			pPHCD[i].friendly = gf_mtRand() % 300;
			pPHCD[i].romVersion = VERSION_GOLD + gf_mtRand() % 2;

			MI_CpuCopy8( YourName, pPHCD[i].trainerName, sizeof(YourName) );
			MI_CpuCopy8( YourNick, pPHCD[i].enemyNickname, sizeof(YourNick) );
			MI_CpuCopy8( courseName, pPHCD[i].courseNameString, sizeof(courseName) );

			if( (gf_mtRand() % 3 ) == 0 )
			{
				MI_CpuCopy8( MyNick, pPHCD[i].myNickname, sizeof(MyNick) );
			}
		}
		// ページ強制上書き
		pPHCD[0].pokeNumber = 0;
		pPHCD[0].actionId = 25;

		pPHCD[1].actionId = 27;
		pPHCD[1].myStepHour = 200;

		pPHCD[2].actionId = 27;
		pPHCD[2].myStepHour = 200;

		pPHCD[3].actionId = 27;
		pPHCD[3].myStepHour = 200;

		pPHCD[4].actionId = 27;
		pPHCD[4].myStepHour = 4000;

		pPHCD[5].actionId = 27;
		pPHCD[5].myStepHour = 200;

		pPHCD[6].actionId = 4;
		pPHCD[6].myStepHour = 40;
		pPHCD[6].yourStepHour = 4000;

		pPHCD[7].actionId = 27;
		pPHCD[7].myStepHour = 40;

		pPHCD[4].pokeNumber = MONSNO_DHIGUDA;
		pPHCD[5].pokeNumber = MONSNO_DAGUTORIO;

		pPHCD[PAGE_NUM-3].actionId = 27;
		pPHCD[PAGE_NUM-2].actionId = 27;

		p_prm->pDiaryData = pPHCD;
	}

	TCB_Add(DebugHosaka_CallApplication, p_app_wk, TCB_PRI_DEBUG);
}

//-----------------------------------------------------------
// PairSyoujyou
//-----------------------------------------------------------
#include "demo/syoujyou.h"
#include "field/script_def.h"
static void PairSyoujyou_SetProc( void* work )
{
	SYOUJYOU_INI* ini = work;

	FS_EXTERN_OVERLAY(syoujyou);

	//オーバーレイプロセス定義データ
	static const PROC_DATA PairSyoujyouProcData = {
		Syoujyou_Init,
		Syoujyou_Main,
		Syoujyou_Exit,
		FS_OVERLAY_ID(syoujyou),
	};

	ini->savedata = GameSystem_GetSaveData( sp_fldsys );
	ini->type = SYOUJYOU_TYPE_PAIR;

	GameSystem_StartSubProc( sp_fldsys, &PairSyoujyouProcData, ini );
}

static void CallPairSyoujyou( TCB_PTR p_tcb, void* p_wk )
{
	D_HOSAKA_APPLICATION_WORK* p_app_wk;

	//タスク消去
	TCB_Delete(p_tcb);

	p_app_wk	= APPLICATION_AllocWork( HEAPID_BASE_DEBUG, sizeof(SYOUJYOU_INI) );
	p_app_wk->SetProcFunction	= PairSyoujyou_SetProc;
	TCB_Add(DebugHosaka_CallApplication, p_app_wk, TCB_PRI_DEBUG);
}

//-----------------------------------------------------------
// NextTrophy:Poke
//-----------------------------------------------------------
#define PKTH_MEDAL_MAX (5)
static void SetMedalist( PKTHLN_SV_DATA_PTR p_sv, int monsno )
{
	int i;

	for( i=0; i<PKTH_MEDAL_MAX; i++ )
	{
		PkthlnSv_SetMedalData( p_sv, i, monsno );
	}
}

static u16 GetMedalistCount( const u8* p_mdl )
{
	int i;
	u16 ret = 0;

	GF_ASSERT( p_mdl );

	for( i=0; i<MONSNO_END; i++ )
	{
		if( MATH_CountPopulation( p_mdl[i] ) == PKTH_MEDAL_MAX )
		{
			ret++;
		}
	}

	return ret;
}

#include "..\application\pokethlon_museum\museum_pokemon_trophy_tbl.dat"
static u8 GetPokemonNextTrophy( u16 mdlst_poke_cnt )
{
	u8 tbl_max;
	u8 i;

	tbl_max = NELEMS(museum_pokemon_trophy_tbl);

	for(i=0; i<tbl_max; i++)
	{
		if( museum_pokemon_trophy_tbl[ i ] <= mdlst_poke_cnt )
		{
			break;
		}
	};

	GF_ASSERT( i-1 >= 0 );

	return museum_pokemon_trophy_tbl[i-1];
}

static void SetPkthNextTrophyPoke( TCB_PTR p_tcb, void* p_wk )
{
	DEBUG_WINDOW_DATA* wp = p_wk;
	SAVEDATA* p_sv;
	PKTHLN_SV_DATA_PTR p_sv_pkth;
	const u8* p_mdl;
	int medalist_cnt;

	p_sv = GameSystem_GetSaveData( sp_fldsys );
	p_sv_pkth = PkthlnSv_GetSaveData( p_sv );
	p_mdl = PkthlnSv_GetMedalDataCnst( p_sv_pkth );
	medalist_cnt = GetMedalistCount( p_mdl );

	{
		int i;
		int next_cnt;

		if( medalist_cnt < museum_pokemon_trophy_tbl[0] )
		{
			next_cnt = GetPokemonNextTrophy( medalist_cnt );
		}
		else
		{
			next_cnt = MONSNO_END;
		}

		for( i=0; i<next_cnt; i++ )
		{
			SetMedalist( p_sv_pkth, 1+i );
		}

		// 情報表示
		{
			STRBUF* strbuf;

			strbuf = STRBUF_Create( 8, HEAPID_BASE_DEBUG );
			STRBUF_SetNumber( strbuf, next_cnt, 3, NUMBER_DISPTYPE_ZERO, NUMBER_CODETYPE_DEFAULT );

			GF_STR_PrintSimple( &wp->win, FONT_SYSTEM, strbuf, 0, 0, MSG_ALLPUT, NULL );

			STRBUF_Delete( strbuf );
		}

		// 上昇音
		Snd_SePlay( SE_JIHANKI );
	}

	// メニュー画面のままにする
	DebugNoExit(p_wk);
}

//-----------------------------------------------------------
// へや 2 OPEN
//-----------------------------------------------------------
static void SetPkthMuseumOpen02( TCB_PTR p_tcb, void* p_wk )
{
	DEBUG_WINDOW_DATA* wp = p_wk;
	EventWork_SetEventFlag( SaveData_GetEventWork(sp_fldsys->savedata),	FE_PKTH_MUSEUM02_OPEN );
	Snd_SePlay( SE_DECIDE );
	DebugNoExit(p_wk);
}

//-----------------------------------------------------------
// へや 3 OPEN
//-----------------------------------------------------------
static void SetPkthMuseumOpen03( TCB_PTR p_tcb, void* p_wk )
{
	DEBUG_WINDOW_DATA* wp = p_wk;
	EventWork_SetEventFlag( SaveData_GetEventWork(sp_fldsys->savedata),	FE_PKTH_MUSEUM03_OPEN );
	Snd_SePlay( SE_DECIDE );
	DebugNoExit(p_wk);
}

//-----------------------------------------------------------
// へや 4 OPEN
//-----------------------------------------------------------
static void SetPkthMuseumOpen04( TCB_PTR p_tcb, void* p_wk )
{
	DEBUG_WINDOW_DATA* wp = p_wk;
	EventWork_SetEventFlag( SaveData_GetEventWork(sp_fldsys->savedata),	FE_PKTH_MUSEUM04_OPEN );
	Snd_SePlay( SE_DECIDE );
	DebugNoExit(p_wk);
}

//-----------------------------------------------------------
// 通信競技レコードリセット(ひとり)
//-----------------------------------------------------------
static void SetPkthResetEventAloneData( TCB_PTR p_tcb, void* p_wk )
{
	int i,r;
	DEBUG_WINDOW_DATA* wp = p_wk;
	PKTH_EVT_DATA evt_dat = {0};
	u16* pBestRecScore;

	pBestRecScore = PkthlnSv_GetBestRecScore( PkthlnSv_GetSaveData( sp_fldsys->savedata ) );

	for( i=0; i<PKTHLN_EVT_MAX; i++ )
	{
		for( r=0; r<BEST_FIVE; r++ )
		{
			evt_dat.RcMs[r].Record = REC_NO_DATA;
		}

		PkthlnSv_SetEvtDataAlone( PkthlnSv_GetSaveData( sp_fldsys->savedata ), i, &evt_dat );

		// ベストレコード初期化
		pBestRecScore[i] = 0;
	}

	Snd_SePlay( SE_DECIDE );
	DebugNoExit(p_wk);
}

//-----------------------------------------------------------
// 通信競技レコードリセット（つうしん）
//-----------------------------------------------------------
static void SetPkthResetEventCommData( TCB_PTR p_tcb, void* p_wk )
{
	int i,r;
	DEBUG_WINDOW_DATA* wp = p_wk;
	PKTH_COMM_EVT_DATA evt_comm_dat = {0};

	for( i=0; i<PKTHLN_EVT_MAX; i++ )
	{
		for( r=0; r<BEST_FIVE; r++ )
		{
			evt_comm_dat.EvtData.RcMs[r].Record = REC_NO_DATA;
		}
		PkthlnSv_SetEvtDataComm( PkthlnSv_GetSaveData( sp_fldsys->savedata ), i, &evt_comm_dat );
	}

	Snd_SePlay( SE_DECIDE );
	DebugNoExit(p_wk);
}

//-----------------------------------------------------------
// 通信競技レコード セット __Pkth_Input__
//-----------------------------------------------------------

static void PkthInputTask( TCB_PTR p_tcb, void* p_wk );

// 定数
enum
{
	// リストタイプ
	D_LIST_TYPE_CRS = 0,
	D_LIST_TYPE_POKE,
	D_LIST_TYPE_EVT,
	D_LIST_TYPE_RANK,

	// コース項目
	D_LIST_CRS_ID = 0,
	D_LIST_CRS_BUNUS,
	D_LIST_CRS_MAX,
	D_SET_CRS_NUM = 1,

	// ポケモン項目
	D_LIST_POKE_NO = 0,
	D_LIST_POKE_SEX,
	D_LIST_POKE_FORM,
	D_LIST_POKE_RARE,
	D_LIST_POKE_MAX,
	D_SET_POKE_NUM = 3,

	// 競技項目
	D_LIST_EVT_NAME = 0,
	D_LIST_EVT_SCORE,
	D_LIST_EVT_MAX,
	D_SET_EVT_NUM = 3,

	// ランクデータ
	D_LIST_RANK_ID = 0,
	D_LIST_RANK_NUM,
	D_LIST_RANK_MAX,
	D_SET_RANK_NUM = 1,
	D_SET_RANK_ID_NUM = 29,
};

//--------------------------------------------------------------
///	モンスターデータ
//==============================================================
typedef struct {
	u32 MonsNo : 9;
	u32 Sex : 2;
	u32 Form : 5;
	u32 Rare : 1;
	u32 padding : 15;
} D_MONS_DATA;

//--------------------------------------------------------------
///	コース毎データ
//==============================================================
typedef struct {
	u32 EvtID : 8;
	u32 Score : 8;		// 獲得得点
	u32 Record : 16;	// 競技レコード
} D_PKTH_RSLT_DATA;

//--------------------------------------------------------------
///	データ保持ワーク
//==============================================================
typedef struct D_PKTH_DATASET_WORK_tag{
	D_MONS_DATA MonsData[ D_SET_POKE_NUM ];
	D_PKTH_RSLT_DATA RsltData[ D_SET_EVT_NUM ];
	u32 CrsID : 8;
	u32 BunusScore : 8;
	u32 RsltScore : 16;
} D_PKTH_DATASET_WORK;

// シングルトン
static D_PKTH_DATASET_WORK wkPkthDataSet = {0};

//--------------------------------------------------------------
///	リスト制御ワーク
//==============================================================
typedef struct {
	u8 seq : 4;
	u8 list_type : 4;
	u8 list_num;		///< 項目合計数
	s8 list_pos;

	u8 list_rank_id; ///< 設定するランクID
	u8 b_direct_exit;
	u8 padding[2];

	GF_BGL_BMPWIN win;
	GF_BGL_BMPWIN win_cap;
	BMPCURSOR* cursor;
	WORDSET* wset;
	MSGDATA_MANAGER* msgman;
} D_PKTH_INPUT_WORK;

typedef enum {
	COMP_LARGE,
	COMP_SMALL,
}COMP_MODE;

//競技毎のレコードの昇順判定
const u8 SortComp[PKTHLN_EVT_MAX] = {
	COMP_SMALL,	//ハードル
	COMP_LARGE, //フラッグ
	COMP_LARGE,	//サークル
	COMP_LARGE,	//カワラ
	COMP_LARGE,	//ＵＦＯ
	COMP_LARGE,	//ジャンプ
	COMP_LARGE,	//マラソン
	COMP_LARGE,	//レスリング
	COMP_LARGE,	//玉投げ
	COMP_LARGE,	//シュート
};

typedef struct SORT_DATA_tag
{
	u16 Record;			//ソート対象となる実データ
	u16 FrmMnsNo[ENTRY_MAX];
}SORT_DATA;

// 値の比較
static BOOL CompValCore(const int inBase, const int inTarget, const COMP_MODE inCompMode)
{
	BOOL rc = FALSE;
	if (inCompMode == COMP_LARGE){
		if (inBase < inTarget){
			rc = TRUE;
		}
	}else if (inCompMode == COMP_SMALL){
		if (inBase > inTarget){
			rc = TRUE;
		}
	}else{
		GF_ASSERT(0);
	}
	return rc;
}

static BOOL CompVal(const int inBase, const int inTarget, const COMP_MODE inCompMode)
{
	BOOL rc = FALSE;

	if (inBase == REC_NO_DATA){		//データの中身が無い場合はＯＫ
		rc = TRUE;
	}else{
		rc = CompValCore(inBase, inTarget, inCompMode);
	}
	return rc;
}

// バブルソート
static void SortData(const COMP_MODE inCompMode, const SORT_DATA *inSortDat, SORT_DATA *ioSortDatAry)
{
	int i;
	int base, target;
	//ベストファイブのレコードと今回のレコードを比較
	base = ioSortDatAry[BEST_FIVE-1].Record;
	target = inSortDat->Record;
	if ( CompVal(base, target, inCompMode) ){
		//ベストファイブを上書き
		ioSortDatAry[BEST_FIVE-1] = *inSortDat;
		//バブルソート
		for(i=BEST_FIVE-1;i>0;i--){
			base = ioSortDatAry[i-1].Record;
			target = ioSortDatAry[i].Record;
			if ( CompVal(base, target, inCompMode) ){
				SORT_DATA data;
				//データ入れ替え
				data = ioSortDatAry[i-1];
				ioSortDatAry[i-1] = ioSortDatAry[i];
				ioSortDatAry[i] = data;
			}else{
				break;
			}
		}
	}
}

static void WriteBestFiveDataAlone( PKTH_EVT_DATA* evt_data, const SORT_DATA* inSortDatAry )
{
	int i,n;

	for(i=0;i<BEST_FIVE;i++){
		evt_data->RcMs[i].Record = inSortDatAry[i].Record;
		for (n=0;n<ENTRY_MAX;n++){
			evt_data->RcMs[i].FrmMnsNo[n] = inSortDatAry[i].FrmMnsNo[n];
		}
	}
}

static void MakeEventDataAlone( PKTH_EVT_DATA* outData )
{
	u8 i,j,n;
	u8 evt_code;
	COMP_MODE comp_mode;
	PKTH_EVT_DATA* evt_data;
	SORT_DATA sort_dat_ary[BEST_FIVE];

	for(i=0;i<ALONE_EVT_MAX;i++){
		//種目コード取得
		evt_code = wkPkthDataSet.RsltData[i].EvtID;
		//種目データ取得
		evt_data = &outData[evt_code];
		//レコード比較方法取得
		comp_mode = SortComp[evt_code];

		//セーブにあるレコード情報をソートデータに書き込む
		for(j=0;j<BEST_FIVE;j++){
			sort_dat_ary[j].Record = evt_data->RcMs[j].Record;
			for (n=0;n<ENTRY_MAX;n++){
				sort_dat_ary[j].FrmMnsNo[n] = evt_data->RcMs[j].FrmMnsNo[n];
			}
		}
		//自分の記録を見てベストファイブ決定
		{
			SORT_DATA sort;
			sort.Record = wkPkthDataSet.RsltData[i].Record;
			//参加ポケ情報
			for(n=0;n<ENTRY_MAX;n++)
			{
				sort.FrmMnsNo[n] = (wkPkthDataSet.MonsData[n].Form << 10) + wkPkthDataSet.MonsData[n].MonsNo;
			}

			//ベストファイブ記録更新処理
			SortData(comp_mode, &sort, sort_dat_ary);
			WriteBestFiveDataAlone(evt_data, sort_dat_ary);
		}
	}
}


// 一人用コースデータ作成
static void MakeCourseData( PKTH_COURSE * outCourseData )
{
	int i;
	int course_id;
	PKTH_COURSE * course_data;

	course_id = wkPkthDataSet.CrsID;
	course_data = &outCourseData[course_id];

	//セーブされている最高得点を上回ったか？
	if ( wkPkthDataSet.RsltScore > course_data->MaxScore ){
		//データ書き換え
		course_data->MaxScore = wkPkthDataSet.RsltScore;
		if ( course_data->MaxScore > PKTHLN_SCORE_MAX ){
			course_data->MaxScore = PKTHLN_SCORE_MAX;
		}
		for(i=0;i<ALONE_EVT_MAX;i++){
			course_data->EvtScore[i] = wkPkthDataSet.RsltData[i].Score;
			if ( course_data->EvtScore[i] > PKTHLN_SCORE_MAX ){
				course_data->EvtScore[i] = PKTHLN_SCORE_MAX;
			}
		}
		for(i=0;i<ENTRY_MAX;i++){
			course_data->MonsData[i].MonsNo = wkPkthDataSet.MonsData[i].MonsNo;
			course_data->MonsData[i].Form = wkPkthDataSet.MonsData[i].Form;
			course_data->MonsData[i].Sex = wkPkthDataSet.MonsData[i].Sex;
			course_data->MonsData[i].Rare = wkPkthDataSet.MonsData[i].Rare;
			course_data->MonsData[i].Rnd = 0;
		}
	}

}


// ベストスコア生成
static void MakeBestRecScore( const PKTH_EVT_DATA *inEvtData, u16 *outData )
{
	u8 i;
	u8 evt_code;
	u16 record;

	for(i=0;i<ALONE_EVT_MAX;i++){
		const PKTH_EVT_DATA *evt_data;
		//種目コード取得
		evt_code = wkPkthDataSet.RsltData[i].EvtID;
		//種目データ取得
		evt_data = &inEvtData[evt_code];
		record = wkPkthDataSet.RsltData[i].Record;
		//現在のベスト1のレコードと今回のレコードを比較
		if ( CompVal(evt_data->RcMs[0].Record, record, COMP_LARGE) ){		//記録更新
			//スコア更新
			outData[evt_code] = wkPkthDataSet.RsltData[i].Score;
		}
	}
}

#define POINT_MAX (200.0)
#define SUB_BASE_POINT (120.0)

static u8 FixPoint(float inPointF)
{
	u8 point;
	u32 tmp;
	tmp = (u32)inPointF;
	if (tmp > POINT_MAX){
		tmp = POINT_MAX;
	}
	point = tmp;
	return point;
}

static void _calc_score( void )
{
	int i;

	// ボーナス点
	wkPkthDataSet.RsltScore = wkPkthDataSet.BunusScore;

	for( i=0; i<D_SET_EVT_NUM; i++ )
	{
		int record;
		float point_f;
		u8 point;

		record = wkPkthDataSet.RsltData[i].Record;
		point_f = (float)record;

		switch(	wkPkthDataSet.RsltData[i].EvtID )
		{
			case PKTHLN_EVT_DASH :
				point_f = 11500.0 / (point_f);
				record *= 30;
				break;
			case PKTHLN_EVT_STEAL :
				point_f *= 3;
				break;
			case PKTHLN_EVT_PUSH :
				point_f *= 3;
				break;
			case PKTHLN_EVT_BREAK :
				// そのまま
				break;
			case PKTHLN_EVT_CATCH :
				point_f = 150.0 - ( SUB_BASE_POINT / ( (point_f * 0.08) + 1.0 ) );
				break;
			case PKTHLN_EVT_JUMP :
				point_f /= 3.5;
				break;
			case PKTHLN_EVT_RUN :
				point_f *= 10;
				record *= 1024;
				break;
			case PKTHLN_EVT_DROP :
				point_f *= 1.5;
				break;
			case PKTHLN_EVT_THROW :
				point_f *= 3;
				break;
			case PKTHLN_EVT_SHOT :
				point_f *= 5;
				point_f += 100;	// 一位だったことにする
				break;

			default : GF_ASSERT(0);
		}

		point = FixPoint(point_f);

		// 合計点加点
		wkPkthDataSet.RsltScore += point;

		wkPkthDataSet.RsltData[i].Record = record;
		wkPkthDataSet.RsltData[i].Score = point;
	}
}

// セーブ
static void _loot_save( TCB_PTR p_tcb, void* p_wk )
{
	DEBUG_WINDOW_DATA* wp = p_wk;
	PKTHLN_SV_DATA_PTR sv = PkthlnSv_GetSaveData( sp_fldsys->savedata );

	// 換算
	_calc_score();

	// ベストレコード セーブ
	MakeBestRecScore( PkthlnSv_GetEvtDataAloneCnst(sv), PkthlnSv_GetBestRecScore(sv) );
	// コース セーブ
	MakeCourseData( PkthlnSv_GetCrsDataAlone(sv) );
	// 競技 セーブ
	MakeEventDataAlone( PkthlnSv_GetEvtDataAlone(sv) );

	{
		int i;
		PKTH_WIN_POKE* pWinPoke;

		pWinPoke = PkthlnWPokeSv_GetSaveData( sp_fldsys->savedata );

		for( i=0; i<D_SET_POKE_NUM; i++ )
		{
			D_MONS_DATA* MonsData = &wkPkthDataSet.MonsData[i];

			// メダル セーブ
			PkthlnSv_SetMedalData( sv, wkPkthDataSet.CrsID, MonsData->MonsNo );
			// 優勝ポケモン セーブ
			pWinPoke[i].MonsNo = MonsData->MonsNo;
			pWinPoke[i].Sex = MonsData->Sex;
			pWinPoke[i].Form = MonsData->Form;
		}
	}

	Snd_SePlay( SEQ_SE_DP_SAVE );

	DebugNoExit( wp );
}

// 入力画面 起動
static void _loot_select( TCB_PTR p_tcb, void* p_wk, int list_type, int list_set )
{
	DEBUG_WINDOW_DATA* wp = p_wk;
	D_PKTH_INPUT_WORK* wkInput;

	wkInput = sys_AllocMemory( HEAPID_BASE_DEBUG ,sizeof(D_PKTH_INPUT_WORK) );
	MI_CpuClear8( wkInput, sizeof(D_PKTH_INPUT_WORK) );

	wkInput->list_type = list_type;

	TCB_Add( PkthInputTask, wkInput, TCB_PRI_DEBUG );

	//タスク消去
	TCB_Delete(p_tcb);
}

//-----------------------------------------------------------
// List Param
//-----------------------------------------------------------
static void LootFunc_Course( TCB_PTR p_tcb, void* p_wk )
{
	_loot_select( p_tcb, p_wk, D_LIST_TYPE_CRS, 0 );
}

static void LootFunc_Poke( TCB_PTR p_tcb, void* p_wk )
{
	_loot_select( p_tcb, p_wk, D_LIST_TYPE_POKE, 0 );
}

static void LootFunc_Event( TCB_PTR p_tcb, void* p_wk )
{
	_loot_select( p_tcb, p_wk, D_LIST_TYPE_EVT, 0 );
}

static void LootFunc_decide( TCB_PTR p_tcb, void* p_wk )
{
	_loot_save( p_tcb, p_wk );
}

//-----------------------------------------------------------
// List Member
//-----------------------------------------------------------
static const LIST_PARAM D_PkthEventLootList[] = {
	{ MSG_PKTH_LOOT_CRS,	(u32)LootFunc_Course },
	{ MSG_PKTH_LOOT_POKE,	(u32)LootFunc_Poke },
	{ MSG_PKTH_LOOT_EVT,	(u32)LootFunc_Event },
	{ MSG_PKTH_LOOT_SAVE,	(u32)LootFunc_decide },
};

// コースIDからイベントIDを取得
#include "..\application\pokethlon\pkthln_crs_tbl.dat"
static u32 GetEventIDByCourse( u8 crs_idx, u8 event_idx )
{
	GF_ASSERT( crs_idx < ALONE_COURSE_NUM );
	GF_ASSERT( event_idx < ALONE_EVT_MAX );

	return crs_evt_tbl[ crs_idx ][ event_idx ];
}

//-----------------------------------------------------------
// ポケスロンデータセット開始
//-----------------------------------------------------------
static void CallPkthDataSet( TCB_PTR p_tcb, void* p_wk )
{
	//タスク消去
	TCB_Delete(p_tcb);

	// デバッグワーク 初期化
	{
		int i;
		// monsnoが0は存在しないので
		for( i=0; i<D_SET_POKE_NUM; i++ )
		{
			if( wkPkthDataSet.MonsData[i].MonsNo == 0 )
			{
				wkPkthDataSet.MonsData[i].MonsNo = 1;
			}
		}
		// コースIDから競技を決定
		for( i=0; i<ALONE_EVT_MAX; i++ )
		{
			wkPkthDataSet.RsltData[i].EvtID = GetEventIDByCourse( wkPkthDataSet.CrsID, i );
		}
	}

	MakeBmpList(NELEMS(D_PkthEventLootList), D_PkthEventLootList, &MainDebugListWindowData);
}

//-----------------------------------------------------------------------------
/**
 *	@brief	ランクデータを取得
 *
 *	@param	int rankID		[in] ランクID
 *	@param	EvtWinNumTotal	[out] 競技の最高得点
 *
 *	@retval ランクデータ項目へのテーブル
 */
//-----------------------------------------------------------------------------
static u32* GetRankData( int rankID, u32* EvtWinNumTotal )
{
	int i;
	u32* rankData;
	PKTH_RNK_DATA* p_rank = PkthlnSv_GetRnkData( PkthlnSv_GetSaveData( sp_fldsys->savedata ) );

	// 競技合計得点
	for(i=0; i<PKTHLN_EVT_MAX; i++)
	{
		*EvtWinNumTotal += p_rank->EvtWinNum[i];
	}

	if( rankID == 0 ){	rankData = &p_rank->AlonePlay; } else
	if( rankID == 1 ){	rankData = &p_rank->AloneWin; } else
	if( rankID == 2 ){	rankData = &p_rank->AloneLose; } else
	if( rankID == 3 ){	rankData = &p_rank->BonusNum; } else
	if( rankID == 4 ){	rankData = EvtWinNumTotal; } else
	if( rankID == 5 ){	rankData = &p_rank->EvtLoseNum; } else
	if( rankID == 6 ){	rankData = &p_rank->CommPlay; } else
	if( rankID == 7 ){	rankData = &p_rank->CommWin; } else
	if( rankID == 8 ){	rankData = &p_rank->CommLose; } else
	if( rankID == 9 ){  rankData = &p_rank->FunNum; } else
	if( rankID >= 10 && rankID < 20 ){	rankData = &p_rank->EvtWinNum[ rankID - 10 ]; } else
	if( rankID == 20 ){	rankData = &p_rank->TouchNum; } else
	if( rankID == 21 ){	rankData = &p_rank->PokeDash; } else
	if( rankID == 22 ){	rankData = &p_rank->PokeJump; } else
	if( rankID == 23 ){	rankData = &p_rank->PokeAttack; } else
	if( rankID == 24 ){	rankData = &p_rank->PokeChange; } else
	if( rankID == 25 ){ rankData = &p_rank->OwnGoal; } else
	if( rankID == 26 ){	rankData = &p_rank->PointGet; } else
	if( rankID == 27 ){	rankData = &p_rank->PokeFail; } else
	if( rankID == 28 ){	rankData = &p_rank->PokeFall; } else
	{ GF_ASSERT(0); }

	return rankData;
}


// コース
static void _pkth_input_print_course( D_PKTH_INPUT_WORK* wk )
{
	int i, k;
	int set_num = D_SET_CRS_NUM;
	int elem_num = D_LIST_CRS_MAX;
	int msg_ofs = MSG_PKTH_CRS_001;

	// リスト描画
	for( i=0; i<set_num; i++ )
	{
		WORDSET_RegisterPkthlnCourse( wk->wset, 0, wkPkthDataSet.CrsID );
		WORDSET_RegisterNumber( wk->wset, 1, wkPkthDataSet.BunusScore, 3, NUMBER_DISPTYPE_ZERO, NUMBER_CODETYPE_DEFAULT );

		for( k=0; k<elem_num; k++ )
		{
			STRBUF* strbuf;

			strbuf = MSGDAT_UTIL_AllocExpandString( wk->wset, wk->msgman, msg_ofs + k, HEAPID_BASE_DEBUG );
			GF_STR_PrintSimple( &wk->win, FONT_SYSTEM, strbuf, 1*8, (k + i*elem_num)*2*8, MSG_NO_PUT, NULL );

			STRBUF_Delete( strbuf );
		}
	}
}

// ポケ
static void _pkth_input_print_poke( D_PKTH_INPUT_WORK* wk )
{
	int i, k;
	int set_num = D_SET_POKE_NUM;
	int elem_num = D_LIST_POKE_MAX;
	int msg_ofs = MSG_PKTH_POKE_001;

	// リスト描画
	for( i=0; i<set_num; i++ )
	{
		WORDSET_RegisterMonsName( wk->wset, 4, wkPkthDataSet.MonsData[i].MonsNo );
		WORDSET_RegisterNumber( wk->wset, 0, wkPkthDataSet.MonsData[i].MonsNo, 3, NUMBER_DISPTYPE_ZERO, NUMBER_CODETYPE_DEFAULT );
		WORDSET_RegisterPokeMonsSex( wk->wset, 1, wkPkthDataSet.MonsData[i].Sex );
		WORDSET_RegisterNumber( wk->wset, 2, wkPkthDataSet.MonsData[i].Form, 2, NUMBER_DISPTYPE_ZERO, NUMBER_CODETYPE_DEFAULT );
		WORDSET_RegisterNumber( wk->wset, 3, wkPkthDataSet.MonsData[i].Rare, 1, NUMBER_DISPTYPE_ZERO, NUMBER_CODETYPE_DEFAULT );

		for( k=0; k<elem_num; k++ )
		{
			STRBUF* strbuf;

			strbuf = MSGDAT_UTIL_AllocExpandString( wk->wset, wk->msgman, msg_ofs + k, HEAPID_BASE_DEBUG );
			GF_STR_PrintSimple( &wk->win, FONT_SYSTEM, strbuf, 1*8, (k + i*elem_num)*2*8, MSG_NO_PUT, NULL );

			STRBUF_Delete( strbuf );
		}
	}
}

// イベント
static void _pkth_input_print_event( D_PKTH_INPUT_WORK* wk )
{
	int i, k;
	int set_num = D_SET_EVT_NUM;
	int elem_num = D_LIST_EVT_MAX;
	int msg_ofs = MSG_PKTH_EVT_NAME;

	// リスト描画
	for( i=0; i<set_num; i++ )
	{
		WORDSET_RegisterPkthlnMatch( wk->wset, 0, wkPkthDataSet.RsltData[i].EvtID );
		WORDSET_RegisterNumber( wk->wset, 1, wkPkthDataSet.RsltData[i].Record, 3, NUMBER_DISPTYPE_ZERO, NUMBER_CODETYPE_DEFAULT );

		for( k=0; k<elem_num; k++ )
		{
			STRBUF* strbuf;

			strbuf = MSGDAT_UTIL_AllocExpandString( wk->wset, wk->msgman, msg_ofs + k, HEAPID_BASE_DEBUG );
			GF_STR_PrintSimple( &wk->win, FONT_SYSTEM, strbuf, 1*8, (k + i*elem_num)*2*8, MSG_NO_PUT, NULL );

			STRBUF_Delete( strbuf );
		}
	}
}

// ランク
static void _pkth_input_print_rank( D_PKTH_INPUT_WORK* wk )
{
	int i, k;

	int set_num = D_SET_RANK_NUM;
	int elem_num = D_LIST_RANK_MAX;
	int msg_ofs = MSG_PKTH_RANK_ID;

	int rankID = wk->list_rank_id;
	u32* RankData;
	u32 EvtWinNumTotal = 0;

	RankData = GetRankData( rankID, &EvtWinNumTotal );

	// リスト描画
	for( i=0; i<set_num; i++ )
	{
		// 項目名レジスト
		{
			STRBUF* strbuf;
			strbuf = MSGDAT_UTIL_AllocExpandString( wk->wset, wk->msgman, msg_rec01 + rankID, HEAPID_BASE_DEBUG );
			WORDSET_RegisterWord( wk->wset, 0, strbuf, PM_NEUTRAL, TRUE, PM_LANG );
			STRBUF_Delete(strbuf);
		}

		// 項目値をレジスト
		WORDSET_RegisterNumber( wk->wset, 2, *RankData, 7, NUMBER_DISPTYPE_ZERO, NUMBER_CODETYPE_DEFAULT );

		for( k=0; k<elem_num; k++ )
		{
			STRBUF* strbuf;

			strbuf = MSGDAT_UTIL_AllocExpandString( wk->wset, wk->msgman, msg_ofs + k, HEAPID_BASE_DEBUG );

			GF_STR_PrintSimple( &wk->win, FONT_SYSTEM, strbuf, 1*8, (k + i*elem_num)*2*8, MSG_NO_PUT, NULL );

			STRBUF_Delete( strbuf );
		}
	}
}

// 描画
static void _pkth_input_print( D_PKTH_INPUT_WORK* wk )
{
	GF_BGL_BmpWinDataFill( &wk->win, FBMP_COL_WHITE );

	switch( wk->list_type )
	{
		case D_LIST_TYPE_CRS :
			_pkth_input_print_course( wk );
			break;
		case D_LIST_TYPE_POKE :
			_pkth_input_print_poke( wk );
			break;
		case D_LIST_TYPE_EVT :
			_pkth_input_print_event( wk );
			break;
		case D_LIST_TYPE_RANK :
			_pkth_input_print_rank( wk );
			break;
		default : GF_ASSERT(0);
	}

	BMPCURSOR_Print( wk->cursor, &wk->win, 0 ,wk->list_pos*2*8 );

	GF_BGL_BmpWinOnVReq( &wk->win );
}

#define INPUT_MSG_CAP_SX (13)
#define INPUT_MSG_CAP_SY (7)

// 初期化
static void _pkth_input_init( D_PKTH_INPUT_WORK* wk )
{

	wk->wset = WORDSET_Create( HEAPID_BASE_DEBUG );
	wk->msgman = MSGMAN_Create(MSGMAN_TYPE_NORMAL, ARC_MSG, NARC_msg_debug_hosaka_dat, HEAPID_FIELD);
	wk->cursor = BMPCURSOR_Create( HEAPID_BASE_DEBUG );

	GF_BGL_BmpWinAdd( sp_fldsys->bgl, &wk->win, GF_BGL_FRAME3_M,
			0, 0, 16, 24, FLD_SYSFONT_PAL, 1 + (INPUT_MSG_CAP_SY*2) * INPUT_MSG_CAP_SX ); // 説明CGXの下にぶら下がる

	// 説明表示
	GF_BGL_BmpWinAdd( sp_fldsys->bgl, &wk->win_cap, GF_BGL_FRAME3_M, 18, 1,
			INPUT_MSG_CAP_SX, INPUT_MSG_CAP_SY*2, FLD_SYSFONT_PAL, 1 );

	GF_BGL_BmpWinDataFill( &wk->win_cap, FBMP_COL_PINK );

	{
		int col = GF_PRINTCOLOR_MAKE( 1, 2, 0 ); // 背景透明
		STRBUF* strbuf = MSGDAT_UTIL_AllocExpandString( wk->wset, wk->msgman, MSG_PKTH_CAP_001, HEAPID_BASE_DEBUG );
		GF_STR_PrintColor( &wk->win_cap, FONT_SYSTEM, strbuf, 4, 0, MSG_ALLPUT, col, NULL );
		STRBUF_Delete( strbuf );
	}

	// リストタイプごとの初期化
	switch( wk->list_type )
	{
		case D_LIST_TYPE_CRS :
			wk->list_num = D_LIST_CRS_MAX * D_SET_CRS_NUM;
			break;
		case D_LIST_TYPE_POKE :
			wk->list_num = D_LIST_POKE_MAX * D_SET_POKE_NUM;
			break;
		case D_LIST_TYPE_EVT :
			wk->list_num = D_LIST_EVT_MAX * D_SET_EVT_NUM;
			break;
		case D_LIST_TYPE_RANK :
			wk->list_num = D_LIST_RANK_MAX * D_SET_RANK_NUM;
			wk->b_direct_exit = TRUE; ///< 直でリスト開放
			break;
		default : GF_ASSERT(0);

	}

	GF_ASSERT( wk->list_num > 0 );

	// リスト描画
	_pkth_input_print( wk );
}

// 回り込みを考慮した加算減算処理
static u32 _set_loop_number( int srcNum, int add, int max, int min )
{
	int point;

	point = srcNum + add;

	if( point >= max ){
		point %= max;
		point += min;
	}else if( point < min ){
		point = point % max;
		point = (max-min) + point;
	}

	HOSAKA_PRINT(
			"srcNum:%d add:%d max:%d min:%d point:%d \n",
			srcNum, add, max, min, point );

	return point;
}

// 数値設定
static void _pkth_input_set_num( D_PKTH_INPUT_WORK* wk, int add )
{
	int i;

	switch( wk->list_type )
	{
		case D_LIST_TYPE_CRS :
			{
				int set = wk->list_pos / D_LIST_CRS_MAX;
				int elem = wk->list_pos % D_LIST_CRS_MAX;

				switch( elem )
				{
					case 0 :
						wkPkthDataSet.CrsID = _set_loop_number( wkPkthDataSet.CrsID, add, ALONE_COURSE_NUM, 0 );
						// コースIDから競技を決定
						for( i=0; i<ALONE_EVT_MAX; i++ )
						{
							wkPkthDataSet.RsltData[i].EvtID = GetEventIDByCourse( wkPkthDataSet.CrsID, i );
						}
						break;
					case 1 :
						wkPkthDataSet.BunusScore = _set_loop_number( wkPkthDataSet.BunusScore,	add, 201, 0 );
						break;
					default : GF_ASSERT(0);
				}
			}
			break;

		case D_LIST_TYPE_POKE :
			{
				int set = wk->list_pos / D_LIST_POKE_MAX;
				int elem = wk->list_pos % D_LIST_POKE_MAX;
				D_MONS_DATA* mons = &wkPkthDataSet.MonsData[set];

				switch( elem )
				{
					case 0 : mons->MonsNo	= _set_loop_number( mons->MonsNo,	add, MONSNO_END+1, 1 );	break;
					case 1 : mons->Sex		= _set_loop_number( mons->Sex,		add, 3, 0 );			break;
					case 2 : mons->Form		= _set_loop_number( mons->Form,		add, 27, 0 );			break;
					case 3 : mons->Rare		= _set_loop_number( mons->Rare,		add, 2, 0 );			break;
					default : GF_ASSERT(0);
				}
			}
			break;

		case D_LIST_TYPE_EVT :
			{
				int set = wk->list_pos / D_LIST_EVT_MAX;
				int elem = wk->list_pos % D_LIST_EVT_MAX;
				D_PKTH_RSLT_DATA* rslt = &wkPkthDataSet.RsltData[set];

				if( elem == 0 )
				{
					Snd_SePlay( SE_GTC_NG );
					// コースから引っ張ってくるので固定
//					rslt->EvtID = _set_loop_number( rslt->EvtID, add, 10, 0 );
				}
				else
				{
					rslt->Record = _set_loop_number( rslt->Record, add, 1000, 0 );
				}
			}
			break;

		case D_LIST_TYPE_RANK :
			{
//				int set = wk->list_pos / D_LIST_RANK_MAX;
				int elem = wk->list_pos % D_LIST_RANK_MAX;
				PKTH_RNK_DATA* p_Rnk = PkthlnSv_GetRnkData( PkthlnSv_GetSaveData( sp_fldsys->savedata ) );

				u32* RankData;
				u32 EvtWinNumTotal = 0;

				RankData = GetRankData( wk->list_rank_id, &EvtWinNumTotal );

				switch( elem )
				{
					case 0 : wk->list_rank_id = _set_loop_number( wk->list_rank_id, add, D_SET_RANK_ID_NUM, 0 ); break;
					case 1 : (*RankData) = _set_loop_number( *RankData, add, 9999999, 0 ); break;
					default : GF_ASSERT(0);
				}
			}
			break;

		default : GF_ASSERT(0);

	}
}

#define CHECK_KEY_CONT( key ) ( (sys.cont & (key) ) == (key) )

// 数値入力処理
static BOOL _pkth_input_main( D_PKTH_INPUT_WORK* wk )
{
	if( (sys.trg & PAD_BUTTON_DECIDE) || (sys.trg & PAD_BUTTON_CANCEL) )
	{
		// 抜ける
		Snd_SePlay( SE_DECIDE );
		return TRUE;
	}
	else if( sys.trg & PAD_KEY_DOWN )
	{
		wk->list_pos = (wk->list_pos + 1) % wk->list_num;
	}
	else if( sys.trg & PAD_KEY_UP )
	{
		wk->list_pos--;
		if( wk->list_pos < 0 ){ wk->list_pos = wk->list_num-1; }
	}
	else if( sys.repeat & PAD_KEY_RIGHT )
	{
		int add = 1;
		if( CHECK_KEY_CONT( PAD_KEY_RIGHT | PAD_BUTTON_R ) ) { add *= 10; } else
		if( CHECK_KEY_CONT( PAD_KEY_RIGHT | PAD_BUTTON_L ) ) { add *= 100; } else
		if( CHECK_KEY_CONT( PAD_KEY_RIGHT | PAD_BUTTON_X ) ) { add *= 1000; } else
		if( CHECK_KEY_CONT( PAD_KEY_RIGHT | PAD_BUTTON_Y ) ) { add *= 10000; }
		_pkth_input_set_num( wk, add );
	}
	else if( sys.repeat & PAD_KEY_LEFT )
	{
		int add = -1;
		if( CHECK_KEY_CONT( PAD_KEY_LEFT | PAD_BUTTON_R ) ) { add *= 10; } else
		if( CHECK_KEY_CONT( PAD_KEY_LEFT | PAD_BUTTON_L ) ) { add *= 100; } else
		if( CHECK_KEY_CONT( PAD_KEY_LEFT | PAD_BUTTON_X ) ) { add *= 1000; } else
		if( CHECK_KEY_CONT( PAD_KEY_LEFT | PAD_BUTTON_Y ) ) { add *= 10000; }
		_pkth_input_set_num( wk, add );
	}
	else
	{
		// 入力なし
		return FALSE;
	}

	// 描画更新
	_pkth_input_print( wk );

	HOSAKA_PRINT( "list_pos:%d \n",wk->list_pos );

	return FALSE;
}

// 数値入力 終了
static void _pkth_input_exit( D_PKTH_INPUT_WORK* wk )
{
	GF_BGL_BmpWinOff( &wk->win );
	GF_BGL_BmpWinDel( &wk->win );

	GF_BGL_BmpWinOff( &wk->win_cap );
	GF_BGL_BmpWinDel( &wk->win_cap );

	WORDSET_Delete( wk->wset );
	MSGMAN_Delete( wk->msgman );
	BMPCURSOR_Delete( wk->cursor );

	sys_FreeMemoryEz( wk );
}

static void PkthInputTask( TCB_PTR p_tcb, void* p_wk )
{
	D_PKTH_INPUT_WORK* wk = p_wk;

	switch( wk->seq )
	{
		case 0 :
			_pkth_input_init( wk );
			wk->seq++;
			/* fallthrow */

		case 1 :
			if( _pkth_input_main( wk ) )
			{
				wk->seq++;
			}
			break;

		case 2 :
			{
				BOOL bDirectExit = wk->b_direct_exit;

				// 終了
				_pkth_input_exit( wk );

				if( bDirectExit )
				{
					FieldSystemProc_SeqHoldEnd();//OBJ等の動作停止解除
					DebugHosaka_FreeTcbAndUnloadOverlay( p_tcb );
				}
				else
				{
					TCB_Delete( p_tcb );
					MakeBmpList(NELEMS(D_PkthEventLootList), D_PkthEventLootList, &MainDebugListWindowData);
				}
			}
			break;

		default : GF_ASSERT(0);
	}
}

//-----------------------------------------------------------
// end of __Pkth_Input__
//-----------------------------------------------------------

//-----------------------------------------------------------
// Pkthln Debug Effort
//-----------------------------------------------------------
#define EFFORT_MAX (4)

extern DEBUG_PKTHLN_WORK DebugPkthlnWk;

static void _effort_func_core( TCB_PTR p_tcb, void* p_wk, int list_idx )
{
	if( list_idx == EFFORT_MAX )
	{
		DebugPkthlnWk.EffortTypeFlg = 0;
	}
	else
	{
		GF_ASSERT( list_idx < EFFORT_MAX );

		DebugPkthlnWk.EffortTypeFlg = 1;
		DebugPkthlnWk.EffortType = list_idx;
	}

	Snd_SePlay( SE_DECIDE );

	DebugNoExit(p_wk);
}

static void EffortFunc_001( TCB_PTR p_tcb, void* p_wk )
{
	_effort_func_core( p_tcb, p_wk, 0 );
}

static void EffortFunc_002( TCB_PTR p_tcb, void* p_wk )
{
	_effort_func_core( p_tcb, p_wk, 1 );
}

static void EffortFunc_003( TCB_PTR p_tcb, void* p_wk )
{
	_effort_func_core( p_tcb, p_wk, 2 );
}

static void EffortFunc_004( TCB_PTR p_tcb, void* p_wk )
{
	_effort_func_core( p_tcb, p_wk, 3 );
}

static void EffortFunc_005( TCB_PTR p_tcb, void* p_wk )
{
	_effort_func_core( p_tcb, p_wk, 4 );
}

static const LIST_PARAM D_PkthEffortList[] = {
	{ MSG_PKTH_EFFORT_001,	(u32)EffortFunc_001 },
	{ MSG_PKTH_EFFORT_002,	(u32)EffortFunc_002 },
	{ MSG_PKTH_EFFORT_003,	(u32)EffortFunc_003 },
	{ MSG_PKTH_EFFORT_004,	(u32)EffortFunc_004 },
	{ MSG_PKTH_EFFORT_005,	(u32)EffortFunc_005 },
};

static void CallEffortList( TCB_PTR p_tcb, void* p_wk )
{
	//タスク消去
	TCB_Delete(p_tcb);

	MakeBmpList( NELEMS(D_PkthEffortList), D_PkthEffortList, &MainDebugListWindowData );
}


static void CallSetPkthRank( TCB_PTR p_tcb, void* p_wk )
{
	_loot_select( p_tcb, p_wk, D_LIST_TYPE_RANK, 0 );
}


#endif // PM_DEBUG